#include <glib.h>

#define GLIB_THREADS_FORCE_QUIT 1  // force quit

gint global_count = 0;
GMutex *global_mutex = NULL;
GTimer *timer = NULL;
static gpointer _thread_func(gpointer data)
{
    gint i = 0;
    gpointer retval = NULL;

    g_mutex_lock(global_mutex);
    for(i=0;i<10000;i++) {
        global_count += i;
    }
    g_usleep(GPOINTER_TO_INT(data)*1000*1000);
    g_print("count:%d, elapsed:%f \n", global_count, g_timer_elapsed(timer, NULL));
    
    g_print("before lock a non-recursion mutex again \n");
    g_mutex_lock(global_mutex);
    g_print("do something... \n");
    g_mutex_unlock(global_mutex);
    g_print("unlock a non-recursion mutex \n");

    g_mutex_unlock(global_mutex);
}

void glib_threads_mutex_non_rec_err(void)
{
    GThread *th1,*th2,*th3;

    timer = g_timer_new();
    g_timer_start(timer);

    global_mutex = g_new0(GMutex, 1);

    g_mutex_init(global_mutex);
    th1 = g_thread_new("th1", _thread_func, GINT_TO_POINTER(3));
    th2 = g_thread_new("th2", _thread_func, GINT_TO_POINTER(2));
    th3 = g_thread_new("th3", _thread_func, GINT_TO_POINTER(1));

#if GLIB_THREADS_FORCE_QUIT
    g_usleep(5*1000*1000);  // sleep 5s
    g_print("ERROR! quit with exception \n");
    exit(-1);
#endif
    g_thread_join(th1);
    g_thread_join(th2);
    g_thread_join(th3);
    g_mutex_clear(global_mutex);
    g_free(global_mutex);

    g_timer_destroy(timer);
}

gint main(gint argc, gchar **argv)
{
    g_test_init(&argc, &argv, NULL);

    g_test_add_func("/thread/mutex", glib_threads_mutex_non_rec_err);

    return g_test_run();
}